// --------------------------------------------------------------------------------------------------------------------
// <copyright file="Serializer.cs" company="Microsoft Corporation">
// The MIT License (MIT)
// 
// Copyright (c) 2014, Microsoft Corporation
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
//  of this software and associated documentation files (the "Software"), to deal
//  in the Software without restriction, including without limitation the rights
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//  copies of the Software, and to permit persons to whom the Software is
//  furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
//  all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//  THE SOFTWARE.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace Microsoft.Robotics.Runtime
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Runtime.Serialization;
    using System.Xml;

    /// <summary>
    /// A reader that reads the message, deserializes it, and sends to a forwarder
    /// </summary>
    public static class Serializer
    {
        /// <summary>
        /// Opens a file and writes an object to it.
        /// </summary>
        /// <typeparam name="T">The object type to write</typeparam>
        /// <param name="fileName">The file name to write to.</param>
        /// <param name="objectToSave">The object to save</param>
        public static void Save<T>(string fileName, T objectToSave)
        {
            Serializer.Save<T>(fileName, objectToSave, null);
        }

        /// <summary>
        /// Opens a file and writes an object to it.
        /// </summary>
        /// <typeparam name="T">The object type to write</typeparam>
        /// <param name="fileName">The file name to write to.</param>
        /// <param name="objectToSave">The object to save</param>
        /// <param name="knownTypes">The set of known types needed for serialization.</param>
        public static void Save<T>(string fileName, T objectToSave, IEnumerable<Type> knownTypes)
        {
            // load the map if there is one
            DataContractSerializer serializer = new DataContractSerializer(typeof(T), knownTypes, 65535, true, false, new SerializationSurrogate(true));
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            settings.NamespaceHandling = NamespaceHandling.OmitDuplicates;
            using (XmlWriter writer = XmlTextWriter.Create(fileName, settings))
            {
                serializer.WriteObject(writer, objectToSave);
            }
        }

        /// <summary>
        /// Opens a file and reads the one object it contains.
        /// </summary>
        /// <typeparam name="T">The object type to deserialize</typeparam>
        /// <param name="fileName">The file name to deserialize from.</param>
        /// <returns>The deserialized object</returns>
        public static T Load<T>(string fileName)
        {
            // load the map if there is one
            using (FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
            {
                return Serializer.Load<T>(fileStream);
            }
        }

        /// <summary>
        /// Deserializes the object in the stream. Does not close the stream.
        /// </summary>
        /// <typeparam name="T">The object type to deserialize</typeparam>
        /// <param name="stream">The stream name to deserialize from.</param>
        /// <returns>The deserialized object</returns>
        public static T Load<T>(Stream stream)
        {
            // load the map if there is one
            DataContractSerializer serializer = new DataContractSerializer(typeof(T), null, 65535, true, false, new SerializationSurrogate(true), new SerializationResolver());
            T result = (T)serializer.ReadObject(stream);
            return result;
        }
    }
}
